/**
 * @package Infinity-Seed
 * @subpackage view
 *
 * @copyright Copyright (C) 2012-2013 Exia.CESI
 * @author Paul MAGNIN, Arthur MERCIER, Jordan RICHET, Cyril SCHUMACHER
 */
package view;

import infinity.seed.CustomFont;
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.net.*;
import java.text.NumberFormat;
import java.util.logging.*;
import javax.swing.*;
import javax.swing.plaf.metal.MetalLookAndFeel;
import save.SaveGrid;
import save.format.SaveDatabase;

/**
 * Fenêtre contenant le Menu.
 * @author Cyril SCHUMACHER <cyril.schumacher at viacesi.fr>
 */
public class MenuWindow {
    // <editor-fold defaultstate="collapsed" desc="Attributs">
    /**
     * Fenetre.
     */
    private JFrame _frame;
    /**private JFrame _frame;
     * Position du curseur (utilise lors du deplacement de la fenetre).
     */
    private static Point point = new Point();
    /**
     * Configurations.
     */
    private infinity.seed.Configuration _configuration;
    /**
     * Largeur de la carte.
     */
    private JFormattedTextField _sizeMapWidth;
    /**
     * Hauteur de la carte.
     */
    private JFormattedTextField _sizeMapHeight;
    /**
     * Gestion des sauvegardes.
     */
    private SaveGrid _save;

    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Méthodes.">
    // <editor-fold defaultstate="collapsed" desc="Constructeur.">
    /**
     * Constructeur.
     */
    public MenuWindow() {
        // Creer une fenetre.
        this._frame = new JFrame();
        
        try {
            // Applique le style Metal. 
            UIManager.setLookAndFeel(new MetalLookAndFeel());

        } catch (UnsupportedLookAndFeelException ex) {
            Logger.getLogger(SimulatorWindow.class.getName()).log(Level.SEVERE, null, ex);
            JOptionPane.showMessageDialog(this._frame.getRootPane(), ex.getMessage());
            System.exit(1);
        }

        // Configurations.
        this._configuration = infinity.seed.Configuration.getInstance();
        
        // Definit l'icone de la fenetre : recupere l'adresse l'image et sa source.
        this._frame.setIconImage(new ImageIcon(getClass().getResource("/resources/SmallLogo.jpg")).getImage());
        // Definit l'action par defaut pour la fermeture de la fenetre.
        this._frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // Initialise les composants de la fenetre.
        _InitializeComponent();
        // Definit la couleur du fond.
        this._frame.setBackground(Color.decode(_configuration.get("jwindow.background")));
        // Cache les contours de la fenetre.
        this._frame.setUndecorated(true);
        // Definit la taille de la fenetre en calculant l'espace utilise.
        this._frame.pack();
        // Centre la fenetre.
        this._frame.setLocationRelativeTo(null);
        // Affiche la fenetre.
        this._frame.setVisible(true);

        // <editor-fold defaultstate="collapsed" desc="Evenements pour la fenêtre".">
        this._frame.addMouseListener(new MouseAdapter() {
            /**
             * Récupère la position du curseur.
             * @param e Parametres.
             */
            @Override
            public void mousePressed(MouseEvent e) {
                point.x = e.getX();
                point.y = e.getY();
            }
        });

        this._frame.addMouseMotionListener(new MouseMotionAdapter() {
            /**
             * Selon la position du curseur, on déplace la fenêtre.
             * @param e Paramètres.
             */
            @Override
            public void mouseDragged(MouseEvent e) {
                JFrame window = (JFrame) e.getSource();
                Point position = window.getLocation();
                window.setLocation(position.x + e.getX() - point.x, position.y + e.getY() - point.y);
            }
        });
        // </editor-fold>
    }
    // </editor-fold>   
    // <editor-fold defaultstate="collapsed" desc="Destructeur.">
    /**
     * Destructeur.
     * @throws Throwable 
     */
    @Override public void finalize() throws Throwable {
        super.finalize();
        this._frame.dispose();
    }
    // </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Initialise les composants de la fenetre.">
    /**
     * Initialise les composants de la fenetre.
     */
    private void _InitializeComponent() {
        // <editor-fold defaultstate="collapsed" desc="Initialisation.">
        // Création de police personnalisee.
        CustomFont customFont = new CustomFont();
        // Style pour les boutons.
        ButtonEvent buttonStyle = new ButtonEvent();

        // Définit le gestionnaire de positionnement principal.
        BorderLayout contentPaneLayout = new BorderLayout();
        this._frame.getContentPane().setLayout(contentPaneLayout);
        // Change la couleur de la bordure.
        this._frame.getRootPane().setBorder(BorderFactory.createLineBorder(Color.black));
        // </editor-fold>
        // <editor-fold defaultstate="collapsed" desc="Barre de titre.">
        JPanel titlePanel = new JPanel();
        titlePanel.setBackground(Color.decode(_configuration.get("jwindow.background")));
        titlePanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
        this._frame.getContentPane().add(titlePanel, BorderLayout.PAGE_START);

        // Bouton "Réduire".
        JButton minimizerButton = new JButton("_");
        minimizerButton.setToolTipText(this._configuration.get("jwindow.minimize.text"));
        minimizerButton.setBackground(titlePanel.getBackground());
        minimizerButton.setOpaque(true);
        minimizerButton.setForeground(Color.WHITE);
        minimizerButton.setFont(new Font(minimizerButton.getFont().getFontName(), minimizerButton.getFont().getStyle(), 15));
        minimizerButton.setBorder(BorderFactory.createEmptyBorder(2,7,2,7));
        titlePanel.add(minimizerButton);
        // <editor-fold defaultstate="collapsed" desc="Evenements pour le composant "minimizerButton".">
        minimizerButton.addMouseListener(new MouseAdapter() {
            /**
             * Lorsque le curseur est sur l'élément.
             */
            @Override public void mouseEntered(MouseEvent e) {
                ((JComponent)e.getSource()).setBackground(Color.decode(_configuration.get("jwindow.minimize.background")));
            }
            /**
             * Lorsque le curseur quitte l'élément.
             */
            @Override public void mouseExited(MouseEvent e) {
                ((JComponent)e.getSource()).setBackground(Color.decode(_configuration.get("jwindow.background")));
            }
        });
        minimizerButton.addActionListener(new ActionListener() {
            /**
             * Ferme la fenetre lorsque le client clique sur ce bouton.
             */
            @Override public void actionPerformed(ActionEvent e) {
                _frame.setState(JFrame.ICONIFIED);
            }
        });
        // </editor-fold>

        // Bouton "Fermer".
        JButton closeButton = new JButton("x");
        closeButton.setToolTipText(this._configuration.get("jwindow.close.text"));
        closeButton.setBackground(titlePanel.getBackground());
        closeButton.setOpaque(true);
        closeButton.setForeground(Color.WHITE);
        closeButton.setFont(new Font(closeButton.getFont().getFontName(), closeButton.getFont().getStyle(), 15));
        closeButton.setBorder(BorderFactory.createEmptyBorder(2,7,2,7));
        titlePanel.add(closeButton);
        // <editor-fold defaultstate="collapsed" desc="Evenements pour le composant "closeButton".">
        closeButton.addMouseListener(new MouseAdapter() {
            /**
             * Lorsque le curseur est sur l'élément.
             */
            @Override public void mouseEntered(MouseEvent e) {
                ((JComponent)e.getSource()).setBackground(Color.decode(_configuration.get("jwindow.close.background")));
            }
            /**
             * Lorsque le curseur quitte l'élément.
             */
            @Override public void mouseExited(MouseEvent e) {
                ((JComponent)e.getSource()).setBackground(Color.decode(_configuration.get("jwindow.background")));
            }
        });
        closeButton.addActionListener(new ActionListener() {
            /**
             * Ferme la fenetre lorsque l'utilisateur clique sur ce bouton.
             */
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
        // </editor-fold>
        // </editor-fold>
        // <editor-fold defaultstate="collapsed" desc="Contenu de la fenêtre.">
        JPanel contentPanel = new JPanel();
        BoxLayout contentLayout = new BoxLayout(contentPanel, BoxLayout.Y_AXIS);
        contentPanel.setLayout(contentLayout);

        // <editor-fold defaultstate="collapsed" desc="Chargement.">
        /**
         * *******************************************************
         * CHARGER LA CARTE.
         * *******************************************************
         */
        FlowLayout saveLayout = new FlowLayout();
        JPanel savePanel = new JPanel();
        savePanel.setBackground(Color.decode(_configuration.get("jwindow.background")));
        savePanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 20, 10));
        savePanel.setLayout(saveLayout);
        this._frame.getContentPane().add(savePanel, BorderLayout.CENTER);

        JButton saveButton = new JButton(this._configuration.get("menu.saveButton.text").toUpperCase());
        saveButton.setToolTipText(this._configuration.get("menu.saveButton.tooltip"));
        saveButton.setFont(customFont.getFont("/resources/open-sans/OpenSans-Regular.ttf", 24));
        saveButton.setBorder(BorderFactory.createEmptyBorder(5, 50, 5, 50));
        savePanel.add(saveButton, saveLayout);
        
        // Lance une exception dans le cas ou aucune base de donnees n'est presente sur la machine.
        try {
            _save = new SaveGrid();
            _save.setBehaviour(new SaveDatabase());
            
            // Si aucune grille n'a ete sauvegarde, on desactive le bouton.
            if (((Boolean)_save.exists()).equals(false)) {
                throw new Exception();
            }
            else {
                saveButton.addActionListener(new SaveButtonEvent());
                saveButton.setBackground(Color.decode(_configuration.get("jbutton.background")));
                saveButton.setForeground(Color.decode(_configuration.get("jbutton.text")));
                saveButton.addMouseListener(buttonStyle);
            }
        }
        catch(Exception e) {
            saveButton.setEnabled(false);
            saveButton.setBackground(Color.decode(this._configuration.get("jbutton.inactive.background")));
            saveButton.setForeground(Color.decode(this._configuration.get("jbutton.inactive.text")));
        }
        // </editor-fold>
        // <editor-fold defaultstate="collapsed" desc="Création de la carte.">
        /**
         * ********************************************************************************************************************************
         * OPTIONS. Integre les options pour la creation de la carte et les
         * informations sur l'application.
         * ********************************************************************************************************************************
         */
        GridLayout optionLayout = new GridLayout(0, 2);
        JPanel optionPanel = new JPanel();
        optionPanel.setLayout(optionLayout);
        optionPanel.setBackground(Color.decode(_configuration.get("jwindow.foreground")));
        this._frame.getContentPane().add(optionPanel, BorderLayout.PAGE_END);

        // Evenements pour les elements contenus dans le panel "createMapPanel".
        CreateButtonEvent createEvent = new CreateButtonEvent();
        
        JPanel createMapPanel = new JPanel();
        BoxLayout createMapLayout = new BoxLayout(createMapPanel, BoxLayout.Y_AXIS);
        createMapPanel.setBorder(BorderFactory.createEmptyBorder(5, 20, 5, 20));
        createMapPanel.setLayout(createMapLayout);
        createMapPanel.setBackground(optionPanel.getBackground());
        optionPanel.add(createMapPanel);
        
        JPanel subCreateMapPanel = new JPanel();
        subCreateMapPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
        subCreateMapPanel.setBackground(optionPanel.getBackground());
        createMapPanel.add(subCreateMapPanel);
        
        JLabel createMapLabel = new JLabel(this._configuration.get("menu.createMapLabel.text").toUpperCase());
        createMapLabel.setFont(customFont.getFont("/resources/open-sans/OpenSans-Semibold.ttf", 20));
        subCreateMapPanel.add(createMapLabel);
        
        GridLayout optionMapLayout = new GridLayout(1, 2);
        JPanel optionMapPanel = new JPanel();
        optionMapPanel.setBackground(optionPanel.getBackground());
        optionMapPanel.setLayout(optionMapLayout);
        optionMapPanel.setBorder(BorderFactory.createEmptyBorder(0, 5, 10, 0));
        createMapPanel.add(optionMapPanel);

        /**
         * *******************************************************
         * FORMAT DES TEXTFIELD.
         * *******************************************************
         */
        // Format du champs : uniquement 3 chiffres. 
        NumberFormat onlyNumberField = NumberFormat.getNumberInstance();
        onlyNumberField.setMaximumIntegerDigits(3);

        /**
         * *******************************************************
         * TAILLE DE LA CARTE.
         * *******************************************************
         */
        // Label.
        JLabel sizeMapLabel = new JLabel(this._configuration.get("menu.sizeMapLabel.text"));
        sizeMapLabel.setFont(customFont.getFont("/resources/open-sans/OpenSans-Regular.ttf", 12));
        optionMapPanel.add(sizeMapLabel);

        // Conteneur qui contiendra les champs de texte (evite que le composant prennent la taille de la cellule).
        JPanel sizeMapPanel = new JPanel();
        sizeMapPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
        sizeMapPanel.setBackground(optionPanel.getBackground());
        optionMapPanel.add(sizeMapPanel);

        // Largeur de la carte.
        this._sizeMapWidth = new JFormattedTextField(onlyNumberField);
        this._sizeMapWidth.setText(this._configuration.get("grid.width"));
        this._sizeMapWidth.setPreferredSize(new Dimension(30, 20));
        this._sizeMapWidth.setBackground(Color.decode(this._configuration.get("jtextfield.background")));
        this._sizeMapWidth.setBorder(BorderFactory.createLineBorder(Color.decode(this._configuration.get("jtextfield.border"))));
        this._sizeMapWidth.addActionListener(createEvent);
        sizeMapPanel.add(this._sizeMapWidth);
        
        JLabel timeMap = new JLabel("x");
        timeMap.setFont(customFont.getFont("/resources/open-sans/OpenSans-Semibold.ttf", 12));
        sizeMapPanel.add(timeMap);

        // Hauteur de la carte.
        this._sizeMapHeight = new JFormattedTextField(onlyNumberField);
        this._sizeMapHeight.setText(this._configuration.get("grid.height"));
        this._sizeMapHeight.setPreferredSize(new Dimension(30, 20));
        this._sizeMapHeight.setBackground(Color.decode(this._configuration.get("jtextfield.background")));
        this._sizeMapHeight.setBorder(BorderFactory.createLineBorder(Color.decode(this._configuration.get("jtextfield.border"))));
        this._sizeMapHeight.addActionListener(createEvent);
        sizeMapPanel.add(this._sizeMapHeight);

        /**
         * *******************************************************
         * CREATION DE LA CARTE.
         * *******************************************************
         */
        JPanel createPanel = new JPanel();
        createPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
        createPanel.setBackground(optionPanel.getBackground());
        createMapPanel.add(createPanel);
        
        JButton createButton = new JButton(this._configuration.get("menu.createButton.text").toUpperCase());
        createButton.setFont(customFont.getFont("/resources/open-sans/OpenSans-Bold.ttf", 12));
        createButton.setBackground(Color.decode(_configuration.get("jbutton.background")));
        createButton.setForeground(Color.decode(_configuration.get("jbutton.text")));
        createButton.setBorder(BorderFactory.createEmptyBorder(5, 30, 5, 30));
        createButton.addMouseListener(buttonStyle);
        createPanel.add(createButton);
        createButton.addActionListener(createEvent);
        // </editor-fold>
        // <editor-fold defaultstate="collapsed" desc="A propos.">
        JPanel aboutPanel = new JPanel();
        aboutPanel.setBorder(BorderFactory.createEmptyBorder(8, 10, 20, 10));
        aboutPanel.setBackground(optionPanel.getBackground());
        aboutPanel.setLayout(new BoxLayout(aboutPanel, BoxLayout.Y_AXIS));
        optionPanel.add(aboutPanel);
        
        JLabel nameProjectLabel = new JLabel(_configuration.get("application.name").toUpperCase());
        nameProjectLabel.setFont(customFont.getFont("/resources/open-sans/OpenSans-Semibold.ttf", 20));
        aboutPanel.add(nameProjectLabel);
        
        JPanel separatorPanel = new JPanel();
        separatorPanel.setBackground(Color.decode(_configuration.get("jwindow.foreground")));
        separatorPanel.setMaximumSize(new Dimension(0,7));
        aboutPanel.add(separatorPanel);

        JLabel copyrightLabel = new JLabel(_configuration.get("application.copyright"));
        copyrightLabel.setFont(customFont.getFont("/resources/open-sans/OpenSans-Regular.ttf", 15));
        aboutPanel.add(copyrightLabel);

        JLabel authorLabel = new JLabel(_configuration.get("application.author"));
        authorLabel.setForeground(Color.GRAY);
        authorLabel.setFont(customFont.getFont("/resources/open-sans/OpenSans-Regular.ttf", 10));
        aboutPanel.add(authorLabel);

        JButton linkButton = new JButton("http://www.exia.cesi.fr/");
        linkButton.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
        linkButton.setForeground(Color.BLUE);
        linkButton.setBackground(aboutPanel.getBackground());
        linkButton.setFont(customFont.getFont("/resources/open-sans/OpenSans-Regular.ttf", 10));

        // <editor-fold defaultstate="collapsed" desc="Evenements pour le composant "linkButton".">
        linkButton.addMouseListener(new MouseAdapter() {
            /**
             * Ouvre une page Internet ayant pour adresse specifique.
             */
            @Override
            public void mouseClicked(MouseEvent e) {
                // Verifie si la plateforme est supporte, si oui, on recupere une instance de la classe.
                if (Desktop.isDesktopSupported()) {
                    Desktop desktop = Desktop.getDesktop();
                    try {
                        // Fournit au navigateur l'adresse.
                        desktop.browse(new URI("http://www.exia.cesi.fr/"));
                    } catch (URISyntaxException | IOException ex) {
                        Logger.getLogger(SimulatorWindow.class.getName()).log(Level.SEVERE, null, ex);
                        JOptionPane.showMessageDialog(_frame.getContentPane(), ex.getMessage(), "Erreur !", JOptionPane.ERROR);
                    }
                }
            }
        });
        // </editor-fold>

        aboutPanel.add(linkButton);
        // </editor-fold>
        // </editor-fold>
    }
    // </editor-fold>
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Evènements.">
    // <editor-fold defaultstate="collapsed" desc="Evenements pour les elements contenus dans le panel "saveButton".">
    /**
     * Evenements pour le bouton "saveButton".
     */
    private class SaveButtonEvent implements ActionListener {
        /**
         * Récupère la grille.
         * @param e 
         */
        @Override public void actionPerformed(ActionEvent e) {
            // Récupère la grille contenu dans la base de données.
            int[][] grid = _save.getGrid();
            Dimension gridDimension = new Dimension(grid.length, grid[0].length);
            // Ouvre la fenêtre contenant la simulation.
            SimulatorWindow simulatorWindow = new SimulatorWindow(grid, gridDimension);
            // Libère la fenêtre.
            _frame.dispose();
        }
    } 
    // </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Evenements pour les elements contenus dans le panel "createMapPanel".">
    /**
     * Evenements pour le bouton "createMapPanel".
     */
    private class CreateButtonEvent implements ActionListener {
        /**
         * Lorsque le client appuye sur la touche Enter.
         * @param e Parametres.
         */
        @Override public void actionPerformed(ActionEvent e) {
            // Verifie si toutes les informations ont ete completees.
            if ((_sizeMapWidth.getText().equals("") == false) && (_sizeMapHeight.getText().equals("") == false)) {
                // Récupère la valeur des champs en entier.
                int mapWidth = Integer.parseInt(_sizeMapWidth.getText());
                int mapHeight = Integer.parseInt(_sizeMapHeight.getText());
                
                // Verifie si la taille ne depasse pas.
                if ((mapWidth > 100) && (mapHeight > 100)) {
                    JOptionPane.showMessageDialog(_frame.getRootPane(), "La dimension de la grille est supérieur à 100.", "Attention !", JOptionPane.INFORMATION_MESSAGE);
                } else if ((mapWidth < 5) && (mapHeight < 5)) {
                    JOptionPane.showMessageDialog(_frame.getRootPane(), "La dimension de la grille est inférieur à 5.", "Attention !", JOptionPane.INFORMATION_MESSAGE);
                }
                else {
                    SimulatorWindow simulatorWindow = new SimulatorWindow(new Dimension(mapWidth, mapHeight));
                    _frame.dispose();
                }
            } else {
                JOptionPane.showMessageDialog(_frame.getRootPane(), "Les champs sont incomplets.", "Attention !", JOptionPane.INFORMATION_MESSAGE);
            }
        }
    }
    // </editor-fold>
    // </editor-fold>
}
